--
-- @Author:      name
-- @DateTime:    2018-03-30 23:05:48
-- @Description: 消息的处理
local skynet = require "skynet"
local mongo = require "skynet.db.mongo"
local server_config = dofile(skynet.getenv("server_config"))

local table_remove = table.remove
local table_insert = table.insert

local MessageHandler = class("MessageHandler")

---------------------------------------------------------
-- Private
---------------------------------------------------------
function MessageHandler:ctor(message_dispatch)
	self.pool = {} --连接池
	self.maxconn = 1
	self.message_dispatch = message_dispatch
	self.disconnected = false


	local conf = server_config.mongo
	self.db_info = {
		host = conf.host,
		port = conf.port,
		username = conf.user,
		password = conf.password,
		authdb = conf.database,
	}
	self.db_name = conf.database

	self.connections = {} --连接池
	self.allocated_connection_num = 0
	self.max_connection_num = 10 

	self:register()
end

--注册本服务里的消息
function MessageHandler:register()
	self.message_dispatch = g.MsgDis()	
	self.message_dispatch:register("start", handler(self,self.start))
	self.message_dispatch:register("mongo_cmd", handler(self,self.mongoCommand))
	self.message_dispatch:registerDefault(handler(self,self.mongoCommand))
end

--从连接池里取一个服务
function MessageHandler:getConnect()
    local connections = self.connections
    if #connections > 0 then
        return table_remove(connections)
    end
    while self.allocated_connection_num >= self.max_connection_num do
        --超上限了，唯有空转等了
        error_log('there is no connection for reusing, waiting for one reused connection')
        skynet.sleep(10)
        if #connections > 0 then
            return table_remove(connections)
        end
    end

    local db_info = self.db_info
    local ok, ret = xpcall(mongo.client, debug.traceback, db_info)
    while not ok do
        error_log('failed to connect mongo',ret)
        skynet.sleep(100)   --one second
        ok, ret = xpcall(mongo.client, debug.traceback, db_info)
    end

    self.allocated_connection_num = self.allocated_connection_num + 1
    return ret
end



---------------------------------------------------------
-- CMD
---------------------------------------------------------

function MessageHandler:start(conf)
	if not conf and type(conf) == "table" then 
		self.db_info = {
			host = conf.host,
			port = conf.port,
			username = conf.user,
			password = conf.password,
			authdb = conf.database,
		}
		self.db_name = conf.database
	end
	return true
end

--执行命令
function MessageHandler:mongoCommand(collection_name, cmd, ...)
	local db = self:getConnect()
	local collection = db[self.db_name][collection_name]
	local func = collection[cmd]
	local ok, ret = xpcall(func, debug.traceback, collection, ...)
    while not ok do
        errlog("___发送消息给mongo错误___", ret)
        skynet.sleep(100)
        print('now retry....')
        ok, ret = xpcall(func, debug.traceback, collection, ...)
    end
    --把连接放回池中
	table_insert(self.connections, db)
	return ret
end


--[[
test
res = g.Message():callService(".mongo", collection, "update", {_id=tonumber(uid)}, {['$set']=user_info}, true)		
--]]


return MessageHandler